#include "ArpSanncer.h"
#include <thread>

DWORD ArpScanner::ScanByInt(IPAddr DestIp, ArpHostInfo &dstHost) {

	ULONG MacAddr[2]{0xfff,0xfff};       /* for 6-byte hardware addresses */
	ULONG PhysAddrLen{6};  /* default to length of six bytes */
	DWORD dwRetVal = SendARP(DestIp, INADDR_ANY, &MacAddr, &PhysAddrLen);
	
	if (dwRetVal == NO_ERROR) {
		ArpHostInfo hostInfo(DestIp, MacAddr, PhysAddrLen);
		dstHost = hostInfo;
	}
	return dwRetVal;
}

ResultCode ArpScanner::ScanTargetIP(TCHAR *ipAddress, ArpHostInfo &dstHost)
{

	IPAddr DestIp = 0;
	IPAddr SrcIp = 0;       /* default for src ip */


	char *DestIpString = NULL;
	char *SrcIpString = NULL;



	InetPton(AF_INET, ipAddress, (VOID*)&DestIp);
#ifdef _DEBUG
	printf("targeIP %u\n", DestIp);
#endif // _DEBUG


	wprintf(L"Sending ARP request for IP address: %s\n", ipAddress);
	//ArpHostInfo dstHost;
	if (ScanByInt(DestIp, dstHost) == NO_ERROR) {
		return ResultCode::OK;
	}
	return ResultCode::TARGET_OFFLINE;
}



ResultCode ArpScanner::ScanSubnet(TCHAR *Subnet_Addr) {

	IPAddr startIP = 0;
	InetPton(AF_INET, Subnet_Addr, (VOID*)&startIP);
	startIP &= (1 << 24) - 1;
#ifdef _DEBUG
	printf("StartIP %u\n", startIP);
#endif // _DEBUG

	ArpHostInfo host[255];
	std::future<ArpHostInfo> f[255];
//	IPAddr destIP[255];
	for (auto i = 1; i < 255; i++) {
		f[i] = std::async(std::launch::async, [startIP, i]() {
			ArpHostInfo info;
			ArpScanner obj;
			IPAddr destIp = startIP | (i << 24);
			obj.ScanByInt(destIp, info);
		//	host[i] = info;
			return info;
		});		
	}

	//printf("here1\n");
	for (auto i = 1; i < 255; i++) {
		ArpHostInfo *hostInfo = &f[i].get();
		if (hostInfo->ipAddress != 0) {
			m_aliveHost.push_back(*hostInfo);
			hostInfo->PrintInfo();
		}
	}
//	printf("here\n");
	return ResultCode::OK;
}
